package com.qujia.station.service.impl;

import com.alibaba.fastjson.JSON;
import com.qq.weixin.mp.aes.AesException;
import com.qq.weixin.mp.aes.WXBizMsgCrypt;
import com.qujia.common.core.domain.AjaxResult;
import com.qujia.common.exception.CustomException;
import com.qujia.common.utils.StringUtils;
import com.qujia.common.utils.http.HttpUtils;
import com.qujia.coupon.domain.AppUserInfo;
import com.qujia.station.controller.EnterpriseController;
import com.qujia.station.domain.Enterprise;
import com.qujia.station.domain.ReceiveMessage;
import com.qujia.station.domain.SysAppUserInfo;
import com.qujia.station.enums.FollowStatusEnum;
import com.qujia.station.mapper.AppUserInfoMapper;
import com.qujia.station.mapper.EnterpriseMapper;
import com.qujia.station.mapper.WxMenuMapper;
import com.qujia.station.service.IThirdPartyWeChatService;
import com.qujia.station.utils.XmlUtils;
import com.qujia.system.domain.SysAppUserInfoUser;
import com.qujia.system.service.AuthorizedAccountDetailsService;
import com.qujia.system.service.IAppUserInfoUserService;
import com.qujia.system.service.impl.AppUserInfoUserServiceImpl;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.json.XML;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


@Service
@Slf4j
public class ThirdPartyWeChatServiceImpl implements IThirdPartyWeChatService {


    @Resource
    private AuthorizedAccountDetailsService authorizedAccountDetailsService;

    @Autowired
    private EnterpriseMapper enterpriseMapper;

    @Autowired
    private EnterpriseController enterpriseController;

    @Resource
    private WxMenuMapper wxMenuMapper;

    //    private static String appid = "wx61be193e633e76cf";
//    private static String appid = "wxa66d9d42ebd12057";

    @Value("${wechat.thirdParty.appid}")
    private  String appid ;


    //    private static String secrect = "825f526be7187691c2b88987f75b2130";
//    private static String secrect = "0d723991f462d84854f4b221e91d8a5a";
    @Value("${wechat.thirdParty.secrect}")
    private  String secrect ;
    private static String token = "1111111111";

    private static String key = "11111111111111111111111111111wqqwewqdwqdqwd";

    @Value("${domain.name}")
    private String domainName;
    @Value("${domain.payName}")
    private String payName;
    private static String prefix = "点击领取会员卡完成推荐:";

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IAppUserInfoUserService appUserInfoService;

    /**
     * 授权事件监听
     */
    @Override
    public String ticketNotify(HttpServletRequest request, HttpServletResponse response) {


        String nonce = request.getParameter("nonce");
        String timestamp = request.getParameter("timestamp");
        String msgSignature = request.getParameter("msg_signature");


        log.info("没有获取到微信发送过来的消息11----------msg_Signature" + msgSignature);
        log.info("微信回调event中获取微信回调的信息-----------------data:{}" + request.getQueryString());
        if (Objects.isNull(msgSignature)) {

            log.info("没有获取到微信发送过来的消息----------");
            return "没有获取到微信发送过来的消息----------";
        } else {
            try {

                InputStream inputStream;
                String postData = null;
                inputStream = request.getInputStream();
                postData = IOUtils.toString(inputStream, "UTF-8");

                //从XML中获取<Encrypt></Encrypt>标签内的密文文本
                Document document = DocumentHelper.parseText(postData);//获取xml字符串
                Element rootElement = document.getRootElement();//获取根目录
                String encrypt = rootElement.elementText("Encrypt");

                log.info("Encrypt:" + encrypt);
                //格式化密文文本，否则没有<ToUserName>标签，会解密失败，参考官方的加解密代码JAVA版本
                String format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%1$s]]></Encrypt></xml>";
                String str = String.format(format, encrypt);

                log.info("---" + nonce + "--" + timestamp + "----" + msgSignature + "---");
                //log.info("获取解密前的postdata的xml:" + xml);
                WXBizMsgCrypt componentAccount = new WXBizMsgCrypt(token, key, appid);

                String xml = componentAccount.decryptMsg(msgSignature, timestamp, nonce, str);
                log.info("获取微信推送的数据解密后明文xml:" + xml);
                if (xml.contains("<InfoType>")) {
                    String InfoType = StringUtils.substringAfter(StringUtils.substringBeforeLast(xml, "]]></InfoType>"), "<InfoType><![CDATA[");
                    log.info("数据类型为--------------------infoType:" + InfoType);
                    if (InfoType.equals("component_verify_ticket")) {
                        String ComponentVerifyTicket = StringUtils.substringAfter(StringUtils.substringBeforeLast(xml, "]]></ComponentVerifyTicket>"), "<ComponentVerifyTicket><![CDATA[");
                        log.info("数据类型为--------------------ComponentVerifyTicket:" + ComponentVerifyTicket);
                        redisTemplate.opsForValue().set("third_party:component_verify_ticket", ComponentVerifyTicket, 60 * 20, TimeUnit.SECONDS);
                        String verifyTicket = redisTemplate.opsForValue().get("third_party:component_verify_ticket").toString();
                        log.info("====================授权票据【ComponentVerifyTicket】：【" + verifyTicket + "】====================");

                    }
                } else {
                    log.info("微信关于账号绑定,解绑,更新账号绑定信息,获取ticket信息出现错误------------");
                    return "微信关于账号绑定,解绑,更新账号绑定信息,获取ticket信息出现错误------------";
                }
            } catch (Exception e) {
                log.info(e.toString());
                log.info(e.getMessage());
            }


//                <xml><AppId><![CDATA[wx61be193e633e76cf]]></AppId>
//<CreateTime>1681492820</CreateTime>
//<InfoType><![CDATA[component_verify_ticket]]></InfoType>
//<ComponentVerifyTicket><![CDATA[ticket@@@_8lKBddBQnsHaFDswHi6AZqn-rgESnFpBosyR53QWladu_Yzq_TWbf_kKTfGysZpmH6gv_VbcFClwb4b0DPSHA]]></ComponentVerifyTicket>
//</xml>
//                String xml = str.substring(0, str.indexOf(">"));
//                String str2=str.substring(str1.length()+1);
//                str="<xml>  <ToUserName><![CDATA[ZetaMing]]></ToUserName>" + str2;
//
//                Map<String, String> Map = (Map<String, String>) new XStream().fromXML(xml);
//                log.info("-------InfoType:"+(String) Map.get("InfoType"));
//                log.info("-------ComponentVerifyTicket:"+(String) Map.get("ComponentVerifyTicket"));
//                if (Objects.nonNull(Map.get("InfoType"))) {
//                    //String infoType=(String) Map.get("InfoType").replace("<![CDATA[","").replace("]]","");
//                    if ("component_verify_ticket".equals(Map.get("InfoType"))) {
//                        String componentVerifyTicket = Map.get("ComponentVerifyTicket");
//                        log.info("获取componentVerifyTicket:" + componentVerifyTicket);
//
//
//                    }

            return "success";
        }

    }


    /**
     * 获取第三方平台访问公众号token
     */
    public String getComponentAccessToken() {
        if (!redisTemplate.hasKey("third_party:component_access_token") || Objects.isNull(redisTemplate.opsForValue().get("third_party:component_access_token").toString())) {
            HashMap<String, Object> paramsHashMap = new HashMap<>();
            paramsHashMap.put("component_appid", appid);
            paramsHashMap.put("component_appsecret", secrect);
            paramsHashMap.put("component_verify_ticket", redisTemplate.opsForValue().get("third_party:component_verify_ticket").toString());

            /** 发送Https请求到微信 */

            try {
                JSONObject resultJson = HttpUtils.doPostJson(
                        "https://api.weixin.qq.com/cgi-bin/component/api_component_token", JSON.toJSONString(paramsHashMap));
                redisTemplate.opsForValue().set("third_party:component_access_token", resultJson.get("component_access_token").toString(), 110, TimeUnit.MINUTES);
            } catch (Exception e) {
                log.info(e.toString());
            }
        }
        return redisTemplate.opsForValue().get("third_party:component_access_token").toString();

    }


    /**
     * 获取第三方平台预授权码
     *
     * @return
     */
    public String getPreAuthCode() {

        // if (!redisTemplate.hasKey("third_party:pre_auth_code")||Objects.isNull(redisTemplate.opsForValue().get("third_party:pre_auth_code").toString())){
        HashMap<String, Object> paramsHashMap = new HashMap<>();
        paramsHashMap.put("component_appid", appid);
        JSONObject resultJson = HttpUtils.doPostJson(
                "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?access_token=" + getComponentAccessToken(), JSON.toJSONString(paramsHashMap));
        log.info("预授权码获取成功-------------" + "third_party:pre_auth_code:" + resultJson.getString("pre_auth_code"));

        return resultJson.getString("pre_auth_code");
        //                    redisTemplate.opsForValue().set("third_party:pre_auth_code",resultJson.get("third_party:pre_auth_code"),1800, TimeUnit.SECONDS);
//                    log.info("预授权码获取成功-------------"+redisTemplate.opsForValue().get("third_party:pre_auth_code").toString());
        //  }

        // return resultJson.getString("third_party:pre_auth_code");
    }


    //刷新授权方令牌执行任务开始
    public String getAccessToken(String authorizerAppid) {
        log.info(domainName + "-----------------");

        log.info("-------------刷新授权方令牌执行任务开始");
        if (Objects.nonNull(authorizerAppid)) {
            HashMap<String, Object> paramsHashMap = new HashMap<>();
            paramsHashMap.put("component_appid", appid);
            paramsHashMap.put("authorizer_appid", authorizerAppid);
            paramsHashMap.put("authorizer_refresh_token", redisTemplate.opsForValue().get("third_party:authorizer_refresh_token:" + authorizerAppid));
            JSONObject resultJson = HttpUtils.doPostJson(
                    "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=" + getComponentAccessToken(), JSON.toJSONString(paramsHashMap));
            if (!resultJson.has("authorizer_refresh_token")) {
                log.error("获取授权方令牌失败，authorizerAppid:[{}]，res:{}", authorizerAppid, resultJson);
                throw new CustomException("get access token fail");
            }
            redisTemplate.opsForValue().set("third_party:authorizer_refresh_token:" + authorizerAppid, resultJson.getString("authorizer_refresh_token"));
//                redisTemplate.opsForValue().set("access_token_"+authorizerAppid);
            //thirdPartyWeChatMapper.modifyToken(authorizerAppid,resultJson.getString("authorizer_access_token"),resultJson.getString("expires_in"),resultJson.getString("authorizer_refresh_token"));
            log.info("authorizerAppid-----------------" + authorizerAppid);
            log.info("i-----------------" + resultJson.toString());
            return resultJson.getString("authorizer_access_token");

        } else {
            log.info("j-----------------");
            return getComponentAccessToken();
        }
    }

    @Override
    public void getaaa(HttpServletResponse resp) throws IOException {
        try {
//            HashMap<String, Object>  hashMap= new HashMap<>();
//            hashMap.put("component_appid",appid);
//            hashMap.put("authorizer_appid","wx045f84bfeb834008");
//            JSONObject infoResultJson=HttpUtils.doPostJson("https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?access_token="+getComponentAccessToken(),JSON.toJSONString(hashMap));
//
//            log.info(infoResultJson.toString()+"infoResultJson-----------------");

            Enterprise enterprise = new Enterprise();


            //详情
            JSONObject Info11 = JSONObject.fromObject("{\"authorizer_info\":{\"nick_name\":\"深斯加油站\",\"head_img\":\"http://wx.qlogo.cn/mmopen/Bn5K9U4j4KwtU18KKWylekgKfpDWxsDib7Z7rBMG53geRnOWSv3l0T6TRaTEBoAh1uVI91RriaKDRiajlYhZsoNFTgicYVNicibGSV/0\",\"service_type_info\":{\"id\":2},\"verify_type_info\":{\"id\":0},\"user_name\":\"gh_97a51973402c\",\"alias\":\"\",\"qrcode_url\":\"http://mmbiz.qpic.cn/mmbiz_jpg/OiblUBVnPiaYQiadvsHMkpSXtGX1Tib7xVJSRpz1oNMmPm5CVT49af75ckwERgGfWImwQRKQmWichjDW6Gaj7pQ7icCA/0\",\"business_info\":{\"open_pay\":0,\"open_shake\":0,\"open_scan\":0,\"open_card\":1,\"open_store\":0},\"idc\":1,\"principal_name\":\"上海深斯能源科技有限公司\",\"signature\":\"致力于提供智慧加油服务\",\"account_status\":1},\"authorization_info\":{\"authorizer_appid\":\"wx045f84bfeb834008\",\"authorizer_refresh_token\":\"refreshtoken@@@OLpTJnJGF76bO9Z_xkHw6KkHsDxq6if44W4dvq86aZ0\",\"func_info\":[{\"funcscope_category\":{\"id\":1},\"confirm_info\":{\"need_confirm\":1,\"already_confirm\":0,\"can_confirm\":1}},{\"funcscope_category\":{\"id\":2},\"confirm_info\":{\"need_confirm\":1,\"already_confirm\":0,\"can_confirm\":1}},{\"funcscope_category\":{\"id\":3},\"confirm_info\":{\"need_confirm\":0,\"already_confirm\":0,\"can_confirm\":0}},{\"funcscope_category\":{\"id\":4}},{\"funcscope_category\":{\"id\":6}},{\"funcscope_category\":{\"id\":8},\"confirm_info\":{\"need_confirm\":1,\"already_confirm\":0,\"can_confirm\":0}},{\"funcscope_category\":{\"id\":89}}]}}");

            JSONObject Info = JSONObject.fromObject(Info11.getJSONObject("authorizer_info"));
//            enterprise.setLeader(Info.getString("nick_name"));

            enterprise.setEnterpriseName(Info.getString("principal_name"));
            enterprise.setCreateUser(1L);
            enterprise.setStatus("1");
            enterprise.setServiceCharge("3.0");
            //类型
            JSONObject type = JSONObject.fromObject(Info.get("service_type_info"));

            int typeId = type.getInt("id");
            if (typeId == 0 || typeId == 1 || typeId == 2) {
                enterprise.setGzhAppId("wx045f84bfeb834008");

            } else {
                enterprise.setAppId("wx045f84bfeb834008");
                enterprise.setOriginId(Info.getString("user_name"));
            }


            AjaxResult ajaxResult = enterpriseController.add(enterprise);

            int i = (int) ajaxResult.get("code");
            if (i == 200)
                resp.sendRedirect(domainName + "/dept/Dept_Group?msg=授权成功");
            else {
                resp.sendRedirect(domainName + "/dept/Dept_Group?msg=授权成功,油企数据填充错误请手动填写");
            }
        } catch (Exception e) {
            resp.sendRedirect(domainName + "/dept/Dept_Group?msg=授权成功,油企数据填充错误请手动填写");
            log.info(e.toString());
        }
    }

    @Override
    public String getMsgByKey(HttpServletRequest request, HttpServletResponse response, String appId) throws IOException {
        String msgSignature = request.getParameter("msg_signature");
        String timeStamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String result = "success";
        if (Objects.isNull(msgSignature)) {
            log.info("没有获取到微信发送过来的消息----------");
            return result;
        } else {
            try {
                InputStream inputStream;
                String postData = null;
                inputStream = request.getInputStream();
                postData = IOUtils.toString(inputStream, "UTF-8");
                //从XML中获取<Encrypt></Encrypt>标签内的密文文本
                Document document = DocumentHelper.parseText(postData);//获取xml字符串
                Element rootElement = document.getRootElement();//获取根目录
                String encrypt = rootElement.elementText("Encrypt");
                log.info("Encrypt:" + encrypt);
                //格式化密文文本，否则没有<ToUserName>标签，会解密失败，参考官方的加解密代码JAVA版本
                String format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%1$s]]></Encrypt></xml>";
                String str = String.format(format, encrypt);
                log.info("---" + nonce + "--" + timeStamp + "----" + msgSignature + "---");
                WXBizMsgCrypt componentAccount = new WXBizMsgCrypt(token, key, appid);
                String xml = componentAccount.decryptMsg(msgSignature, timeStamp, nonce, str);
                log.info("获取微信推送的数据解密后明文xml:" + xml);
                org.json.JSONObject jsonObject = XML.toJSONObject(xml);
                log.info("获取微信推送的数据解密后明文json:" + jsonObject);
                ReceiveMessage receiveMessage = JSON.parseObject(jsonObject.get("xml").toString(), ReceiveMessage.class);
                String event = receiveMessage.getEvent();
                if (ReceiveMessage.SUBSCRIBE.equals(event)) {// 关注
                    if (StringUtils.isNotEmpty(receiveMessage.getEventKey())) { // 扫推荐码关注
                        // 回复消息
                        result = getTextResult(receiveMessage, componentAccount, timeStamp, nonce);
                    }
                    updateFollowStatus(receiveMessage.getFromUserName(), FollowStatusEnum.SUBSCRIBE.getCode(), appId);
                    return result;
                }
                if (ReceiveMessage.UNSUBSCRIBE.equals(event)) {// 取关
                    //更新用户信息表
                    updateFollowStatus(receiveMessage.getFromUserName(), FollowStatusEnum.UNSUBSCRIBE.getCode(), appId);
                    return result;
                }
                if (ReceiveMessage.SCAN.equals(event)) { // 扫推荐码进入公众号
                    // 发送文本消息
                    result = getTextResult(receiveMessage, componentAccount, timeStamp, nonce);
                    return result;
                }
            } catch (Exception e) {
                log.info(e.toString());
                log.info(e.getMessage());
            }
            return result;
        }
    }

    private void updateFollowStatus(String openId, String status, String appId) {
        SysAppUserInfoUser appUserInfo = new SysAppUserInfoUser();
        appUserInfo.setFollowStatus(status);
        appUserInfo.setBlogOpenid(openId);
        List<Enterprise> enterprises = enterpriseMapper.selectEnterpriseByAppId(appId);
        if (CollectionUtils.isNotEmpty(enterprises)) {
            for (Enterprise enterpris : enterprises) {
                appUserInfo.setEnterpriseId(enterpris.getEnterpriseId());
                appUserInfoService.updateFollowStatus(appUserInfo);
            }
        }
    }

    private String getTextResult(ReceiveMessage receiveMessage, WXBizMsgCrypt pc, String timeStamp, String nonce) throws AesException {
        String result = "";
        String eventKey = receiveMessage.getEventKey();
        eventKey = eventKey.replace("qrscene_", "");
        SysAppUserInfoUser appUserInfo = JSON.parseObject(eventKey, SysAppUserInfoUser.class);
        String content = prefix + payName + "/" + appUserInfo.getEnterpriseId() + "/my?recommenderId=" + appUserInfo.getUserId();
        String replyTextMsg = String.format(ReceiveMessage.replyTextMsg, receiveMessage.getFromUserName(), receiveMessage.getToUserName(), new Date().getTime(), content);
        result = pc.encryptMsg(replyTextMsg, timeStamp, nonce);
        return result;
    }


    /**
     * 授权回调
     */
    @Override
    public void bindWxNotify(String authCode, Integer expiresIn, HttpServletResponse resp) throws IOException {
        try {
            log.info("授权成功进来回调------------------------");
            // redisTemplate.delete("third_party:pre_auth_code");
            HashMap<String, Object> paramsHashMap = new HashMap<>();
            paramsHashMap.put("component_appid", appid);
            paramsHashMap.put("authorization_code", authCode);
            //回调信息
            JSONObject resultJson = HttpUtils.doPostJson(
                    "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=" + getComponentAccessToken(), JSON.toJSONString(paramsHashMap));
            JSONObject authorizerInfo = JSONObject.fromObject(resultJson.get("authorization_info"));

            log.info("*-----authCode" + authCode);
            log.info("---" + resultJson.toString() + "-----------resultJson");


            //appid
            String componentAppid = authorizerInfo.getString("authorizer_appid");

            //刷新码
            redisTemplate.opsForValue().set("third_party:authorizer_refresh_token:" + componentAppid, authorizerInfo.getString("authorizer_refresh_token"));

            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("component_appid", appid);
            hashMap.put("authorizer_appid", componentAppid);
            JSONObject infoResultJson = HttpUtils.doPostJson("https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?access_token=" + getComponentAccessToken(), JSON.toJSONString(hashMap));

            log.info(infoResultJson.toString() + "infoResultJson-----------------");

            Enterprise enterprise = new Enterprise();


            //详情
            JSONObject Info = JSONObject.fromObject(infoResultJson.get("authorizer_info"));
            log.info(Info.toString() + "Info-----------------");

//       enterprise.setEnterpriseName(Info.getString("principal_name"));

            //类型
            JSONObject type = JSONObject.fromObject(Info.get("service_type_info"));

            int typeId = type.getInt("id");
            if (typeId == 0 || typeId == 1 || typeId == 2) {
                enterprise.setGzhAppId(componentAppid);

            } else {
                enterprise.setAppId(componentAppid);
                enterprise.setOriginId(Info.getString("user_name"));
            }
            enterprise.setCreateUser(1L);
            enterprise.setStatus("1");
            enterprise.setServiceCharge("3.0");
            AjaxResult ajaxResult = enterpriseController.add(enterprise);

            int i = (int) ajaxResult.get("code");
            if (i == 200)
                resp.sendRedirect(domainName + "/dept/Dept_Group?msg=授权成功");
            else {
                resp.sendRedirect(domainName + "/dept/Dept_Group?msg=授权成功,油企数据填充错误请手动填写");
            }
        } catch (Exception e) {
            resp.sendRedirect(domainName + "/dept/Dept_Group?msg=授权成功,油企数据填充错误请手动填写");
            log.info(e.toString());
        }
    }

    /**
     * @return 获取授权二维码链接
     */
    @Override
    public String getQRCode() {
        return "https://mp.weixin.qq.com/cgi-bin/componentloginpage?" + "component_appid=" + appid + "&pre_auth_code=" + getPreAuthCode() + "&redirect_uri=" + domainName + "/prod-api/thirdParty/weChat/bindWxNotify";
    }


}
